from django.shortcuts import render
from django.views import View
from django.http import JsonResponse
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from apps.oauth.models import OAuthQQUser
from django.contrib.auth import login
import json
import re
from django_redis import get_redis_connection
from itsdangerous import TimedJSONWebSignatureSerializer
from apps.user1.models import User
from apps.carts.utils import megre_cart


# Create your views here.
class QQLoginUrlView(View):
    def get(self,request):
        # 1、初始化生成qq对象
        QQ = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                     redirect_uri=settings.QQ_REDIRECT_URI, state=None)

        # 2、使用QQ对象生成跳转链接
        login_url = QQ.get_qq_url()

        return JsonResponse({'code': 0, 'login_url': login_url, 'errmsg': 'ok'})

class OauthBackView(View):
    def get(self, request):
        # 1、获取code数据，是查询字符串形式
        code = request.GET.get('code')
        if code is None:
            return JsonResponse({"code": 400, 'errmsg': '缺少code参数'}, status=400)
        # 2、根据code数据获取access_token
        QQ = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                     redirect_uri=settings.QQ_REDIRECT_URI, state=None)
        access_token = QQ.get_access_token(code)
        # 3、根据access_token数据获取openid
        openid = QQ.get_open_id(access_token)
        # 4、判断oepnid是否绑定过美多用户，查询QQ表进行判断是否绑定
        try:
            # 如果根据openid查询到数据，则说明以前存储过数据，和美多用已经进行过绑定，该用户可以直接进行登录。
            qq = OAuthQQUser.objects.get(openid=openid)
        except:
            # 捕获到异常，说明get放没有查询到数据，则该openid没有存储过，则需要进行用户绑定,
            # 因为前端只接收access_token，它只是一个字段名，和上面的access_token变量没有任何关系
            # 需要对openid进行加密
            tjs = TimedJSONWebSignatureSerializer(settings.SECRET_KEY,300)
            openid_token = tjs.dumps({'openid':openid}).decode()
            return JsonResponse({'code': 300,'access_token':openid_token})

        # 没有异常，则进行登录操作，需要状态保持 需要在cookie写入用户名
        user = qq.user  # OAuthQQUser关联美多用户外键user
        login(request, user)  # user 是美多用户
        response = JsonResponse({'code': 0})
        response.set_cookie('username', user.username)

        # 合并购物车
        response = megre_cart(request, response, user)

        return response

    def post(self,request):

        # 1、接受前端传递的json数据 是bytes类型数据
        json_data = request.body.decode()
        # 2、将json转化字典数据
        dict_data = json.loads(json_data)
        # 3、从字典中提取相关的字段数据  dict_data['username'] 数据不存在抛出异常
        mobile = dict_data.get('mobile')
        password = dict_data.get('password')
        sms_code = dict_data.get('sms_code')  # 前端用户输入的短信数据
        # 获取加密的opedid数据
        access_token = dict_data.get('access_token')
        # 解密操作
        tjs = TimedJSONWebSignatureSerializer(settings.SECRET_KEY, 300)
        try:
            oepnid_dict = tjs.loads(access_token)
        except:
            # 解密失败
            return JsonResponse({'code': 400, 'errmsg': '无效的openid值'}, status=400)
        # 提取openid
        openid = oepnid_dict.get('openid')
        # 4、验证字段数据
        # 4-1、验证数据完整性all方法中如果有空值会返回false
        if not all([mobile, password,sms_code]):
            return JsonResponse({'code': 400, 'errmsg': '参数不完整'}, status=400)
        # 4-2、判断手机号格式
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'code': 400, 'errmsg': '手机号格式不正确'}, status=400)
        # 4-3、判断密码格式
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return JsonResponse({'code': 400, 'errmsg': '密码格式不正确'}, status=400)
        # 4-4、短信验证判断
        # 连接redis
        conn = get_redis_connection('verify')
        # 获取reids中存储的短信验证码
        real_code = conn.get('sms_code_%s' % mobile)
        # 判断real_code是否超过有效期
        if real_code is None:
            return JsonResponse({'code': 400, 'errmsg': '验证码失效'}, status=400)
        # 判断用户输入的短信验证码和redis中的是否一致
        if sms_code != real_code.decode():
            return JsonResponse({'code': 400, 'errmsg': '验证码输入错误'}, status=400)

        # 5、将数据保存在数据库中，将用户和opendi保存在一起进行绑定
        # 5-1 获取保存的数据用户user和openid
        try:
            user = User.objects.get(mobile=mobile)
        except:
            # 捕获到异常说明手机号没有注册过美多用户，使用该手机号注册一个新用户
            user = User.objects.create_user(username=mobile, mobile=mobile, password=password)

        # 5-2 将用户和openID进行保存
        OAuthQQUser.objects.create(user=user, openid=openid)
        # 绑定成功，需要进行状态保持,第一个参数request对象,第二个参数是用户对象
        login(request, user)
        response = JsonResponse({'code': 0, 'errmsg': 'ok'})
        response.set_cookie('username', user.username)

        # 合并购物车
        response = megre_cart(request, response, user)

        # 6、返回结果
        return response
